home *** CD-ROM | disk | FTP | other *** search
/ HPAVC / HPAVC CD-ROM.iso / ABUSESRC.ZIP / AbuseSrc / macabuse / imlib / supmorph.c < prev    next >
C/C++ Source or Header  |  1997-05-20  |  9KB  |  369 lines

  1. #include "supmorph.hpp"
  2. #include "specs.hpp"
  3. #include "timage.hpp"
  4. #include "timing.hpp"
  5. #include "filter.hpp"
  6. #include "video.hpp"
  7. #include "jrand.hpp"
  8.  
  9. #define p_swap(x,y) { x^=y; y^=x; x^=y; }
  10. #define p_dist(x1,y1,x2,y2) (((int)(x1)-(int)x2)*((int)(x1)-(int)x2)+      \
  11.                              ((int)(y1)-(int)y2)*((int)(y1)-(int)y2))
  12.  
  13. super_morph::super_morph(trans_image *hint1, trans_image *hint2, 
  14.              int aneal_steps, void (*stat_fun)(int))
  15. {
  16.   int x,y,w1=hint1->width(),
  17.           h1=hint1->height(),
  18.           w2=hint2->width(),
  19.           h2=hint2->height();
  20.   if (w1>w2) w=w1; else w=w2;
  21.   if (h1>h2) h=h1; else h=h2;
  22.   unsigned char *dp;
  23.  
  24.   /************************ count up the number of hints ****************************/
  25.   unsigned short hints1[256],hints2[256];
  26.   memset(hints1,0,256*2);
  27.   memset(hints2,0,256*2);
  28.  
  29.   dp=hint1->t_data();
  30.   for (y=0;y<h1;y++)
  31.   {
  32.     x=0;
  33.     while (x<w1)
  34.     {      
  35.       x+=*dp;      // skip over space
  36.       dp++;
  37.       if (x<w1)
  38.       {
  39.     int rl=*(dp++);
  40.     while (rl--) { hints1[*(dp++)]++; x++; }
  41.       }
  42.     }
  43.   }
  44.  
  45.   // hint2 image2
  46.   dp=hint2->t_data();
  47.   for (y=0;y<h2;y++)
  48.   {
  49.     x=0;
  50.     while (x<w2)
  51.     {      
  52.       x+=*dp;      // skip over space
  53.       dp++;
  54.       if (x<w2)
  55.       {
  56.     int rl=*(dp++);
  57.     while (rl--) { hints2[*(dp++)]++; x++; }
  58.       }
  59.     }
  60.   }
  61.  
  62.  
  63.   /****************** now sum up hints and alloc memory for movers *************/
  64.   unsigned short start1[256],start2[256],
  65.                  totals[256],
  66.                  start=0,*h1p=hints1,*h2p=hints2;
  67.   unsigned char hint_color[256],total_hints=0;
  68.  
  69.   for (y=0;y<256;y++,h1p++,h2p++)
  70.     if (*h1p)
  71.     {
  72.       if (*h2p==0)  
  73.       {
  74.     t=0; 
  75.     return ;
  76.       }
  77.       start1[y]=start2[y]=start;       // specify start of hint range
  78.       if (*h1p>*h2p)
  79.         totals[y]=*h1p;
  80.       else totals[y]=*h2p;
  81.       start+=totals[y];
  82.       hint_color[total_hints++]=y;      
  83.     }
  84.  
  85.   t=start;
  86.   movers=(unsigned char *)jmalloc(t*4,"morph movers");
  87.   
  88.   
  89.   /**************** Now scan the images again setup hints *********************/
  90.   dp=hint1->t_data();
  91.   for (y=0;y<h1;y++)
  92.   {
  93.     x=0;
  94.     while (x<w1)
  95.     {      
  96.       x+=*dp;      // skip over space
  97.       dp++;
  98.       if (x<w1)
  99.       {
  100.     int rl=*(dp++);
  101.     while (rl--) 
  102.     {
  103.       int maddr=(start1[*(dp++)]++)*4;
  104.       movers[(maddr++)]=x;
  105.       movers[maddr]=y;
  106.       x++;
  107.     }
  108.       }
  109.     }
  110.   }  
  111.  
  112.   dp=hint2->t_data();
  113.   for (y=0;y<h2;y++)
  114.   {
  115.     x=0;
  116.     while (x<w2)
  117.     {      
  118.       x+=*dp;      // skip over space
  119.       dp++;
  120.       if (x<w2)
  121.       {
  122.     int rl=*(dp++);
  123.     while (rl--) 
  124.     {
  125.       int maddr=(start2[*(dp++)]++)*4+2;
  126.       movers[(maddr++)]=x;
  127.       movers[maddr]=y;
  128.       x++;
  129.     }
  130.       }
  131.     }
  132.   }  
  133.  
  134.   /********* if hint sizes don't match duplicate the smaller until sizes are equal **********/
  135.   for (start=0,x=0;x<total_hints;x++)
  136.   {
  137.     y=hint_color[x];
  138.     int dups;
  139.     for (dp=movers+start1[y]*4,dups=totals[y]-hints1[y];dups;dups--)
  140.     {
  141.       *dp=*(dp-4); dp++;      // copy previous x,y position
  142.       *dp=*(dp-4); dp++;
  143.       dp+=2;    
  144.     }
  145.     start1[y]-=2*totals[y]-hints1[y];        // set the start back to the begining of hint range
  146.   }
  147.  
  148.   for (start=0,x=0;x<total_hints;x++)
  149.   {
  150.     y=hint_color[x];
  151.     int dups;
  152.     for (dp=movers+start2[y]*4+2,dups=totals[y]-hints2[y];dups;dups--)
  153.     {
  154.       *dp=*(dp-4); dp++;      // copy previous x,y position
  155.       *dp=*(dp-4); dp++;
  156.       dp+=2;    
  157.     }
  158.     start2[y]-=hints2[y];        // set the start back to the begining of hint range
  159.   }
  160.  
  161.  
  162.   /******* Now apply simulated annealing to solve for a smaller total distance ********/ 
  163.   int rand_on=0;
  164.   for (y=0;y<aneal_steps;y++)
  165.   {
  166.     if (stat_fun)
  167.       stat_fun(y);
  168.     dp=movers;    
  169.     for (x=0;x<total_hints;x++)
  170.     {
  171.       int hc=hint_color[x];
  172.       int a,z=totals[hc];
  173.       unsigned char *range_start=dp;
  174.       for (a=0;a<z;a++,dp+=4)
  175.       {
  176.     unsigned char *swap=range_start+(rtable[((rand_on++)&(RAND_TABLE_SIZE-1))]%z)*4; 
  177.     int d_old=p_dist(dp[0],dp[1],dp[2],dp[3])+p_dist(swap[0],swap[1],swap[2],swap[3]);
  178.     int d_new=p_dist(dp[0],dp[1],swap[2],swap[3])+p_dist(swap[0],swap[1],dp[2],dp[3]);
  179.     if (d_new<d_old)
  180.     {
  181.       unsigned char s;
  182.       s=swap[2]; swap[2]=dp[2]; dp[2]=s;
  183.       s=swap[3]; swap[3]=dp[3]; dp[3]=s;
  184.     }
  185.       }      
  186.     }    
  187.   }
  188. }
  189.  
  190. smorph_player::smorph_player(super_morph *m, palette *pal, image *i1, image *i2, int frames, int dir)
  191. {
  192.   int i,x1,y1,x2,y2;
  193.   unsigned char *d=m->movers,*paddr=(unsigned char *)pal->addr(),*pa;
  194.   stepper *p;
  195.   p=steps=(stepper *)jmalloc(sizeof(stepper)*m->t,"smorph steps");
  196.   f_left=frames;
  197.   frames--;
  198.   t=m->t;
  199.   w=m->w; h=m->h;
  200.  
  201.   for (i=0;i<t;i++,p++)
  202.   {    
  203.     x1=*(d++);
  204.     y1=*(d++);
  205.     x2=*(d++);
  206.     y2=*(d++);
  207.     
  208.     unsigned char r1,g1,b1,r2,g2,b2;
  209.     pa=paddr+(int)(*(i1->scan_line(y1)+x1))*3;
  210.     r1=*(pa++);
  211.     g1=*(pa++);
  212.     b1=*(pa++);
  213.     
  214.     pa=paddr+(int)(*(i2->scan_line(y2)+x2))*3;
  215.     r2=*(pa++);
  216.     g2=*(pa++);
  217.     b2=*(pa++);
  218.  
  219.     p->r=r1<<16;
  220.     p->g=g1<<16;
  221.     p->b=b1<<16;
  222.  
  223.     p->dr=(long)(((int)r2-(int)r1)<<16)/frames;
  224.     p->dg=(long)(((int)g2-(int)g1)<<16)/frames;
  225.     p->db=(long)(((int)b2-(int)b1)<<16)/frames;
  226.  
  227.     if (dir<0)
  228.     {
  229.       x1=w-x1-1;
  230.       x2=w-x2-1;
  231.     }
  232.     p->dx=((x2-x1)<<16)/frames;
  233.     p->dy=((y2-y1)<<16)/frames;
  234.     p->x=x1<<16;
  235.     p->y=y1<<16;
  236.   }
  237.  
  238.   hole=(unsigned char *)jmalloc(w*h,"hole image");
  239. }
  240.  
  241.  
  242.  
  243.  
  244.  
  245. int smorph_player::show(image *screen, int x, int y, color_filter *fil, palette *pal,
  246.             int blur_threshold)
  247. {  
  248.   if (f_left)
  249.   {
  250.     int i,px,py,ix,iy;
  251.     short x1,y1,x2,y2;
  252.     screen->get_clip(x1,y1,x2,y2);
  253.     screen->add_dirty(x,y,x+w-1,y+h-1);
  254.     stepper *ss;
  255.     memset(hole,0,w*h);
  256.     unsigned char *paddr=(unsigned char *)pal->addr();
  257.     for (ss=steps,i=0;i<t;i++,ss++)
  258.     {
  259.       ix=(ss->x>>(16));
  260.       iy=(ss->y>>(16));
  261.       px=ix+x;
  262.       py=iy+y;
  263.       if (px>=x1 && px<=x2 && py>=y1 && py<=y2)                 
  264.       {
  265.         hole[ix+iy*w]=*(screen->scan_line(py)+px)=fil->lookup_color(ss->r>>(19),
  266.                                     ss->g>>(19),
  267.                                     ss->b>>(19));
  268.       }
  269.       ss->x+=ss->dx;
  270.       ss->y+=ss->dy;
  271.       ss->r+=ss->dr;
  272.       ss->g+=ss->dg;
  273.       ss->b+=ss->db;          
  274.     }
  275.     f_left--;
  276.     if (!f_left)    // skip hole fills and smoothing on last frame
  277.       return 1;
  278.  
  279.     unsigned char *ll=hole+1,*tl=hole+w+1,*nl=hole+w*2+1;
  280.     for (iy=1;iy<h-1;iy++)    // now scan the for holes to fill
  281.     {
  282.       for (ix=1;ix<w-1;ix++,ll++,tl++,nl++)
  283.       {
  284.     if (x+ix>=x1 && x+ix<=x2 && y+iy>=y1 && y+iy<=y2)
  285.     {
  286.       int t=0;
  287.       unsigned char *pa;
  288.       int r=0,g=0,b=0;
  289. /*      if (*(tl-1)) t++;
  290.       if (*(tl+1)) t++;
  291.       if (*ll) t++;
  292.       if (*nl) t++;*/
  293.  
  294.       if (*(tl-1)) { t++; pa=paddr+(*(tl-1))*3; r+=*(pa++); g+=*(pa++); b+=*(pa++); }
  295.       if (*(tl+1)) { t++; pa=paddr+(*(tl+1))*3; r+=*(pa++); g+=*(pa++); b+=*(pa++); }
  296.       if (*(ll)) { t++; pa=paddr+(*ll)*3; r+=*(pa++); g+=*(pa++); b+=*(pa++); }
  297.       if (*(nl)) { t++; pa=paddr+(*nl)*3; r+=*(pa++); g+=*(pa++); b+=*(pa++); }        
  298.  
  299.       if (*tl)
  300.       {
  301.         if (t)
  302.         {
  303.           pa=paddr+(*tl)*3;
  304.           r/=t; g/=t; b/=t;
  305.           int dist=((int)(*pa)-r)*((int)(*pa)-r); pa++;
  306.           dist+=((int)(*pa)-g)*((int)(*pa)-g); pa++;
  307.           dist+=((int)(*pa)-b)*((int)(*pa)-b);
  308.           if (dist>blur_threshold)
  309.             *(tl)=*(screen->scan_line(y+iy)+x+ix)=fil->lookup_color(r>>3,g>>3,b>>3);
  310.         } else *(tl)=*(screen->scan_line(y+iy)+x+ix)=0; // kill single pixels
  311.       }
  312.       else if (t>=3)
  313.         *(tl)=*(screen->scan_line(y+iy)+x+ix)=fil->lookup_color((r/t)>>3,(g/t)>>3,(b/t)>>3);
  314.     }
  315.       }
  316.       ll+=2;
  317.       tl+=2;
  318.       nl+=2;      
  319.     }
  320.     return 1;
  321.   } else return 0;
  322. }
  323.  
  324.  
  325.  
  326.  
  327. /*void free_up_memory() { dprintf("you're screwed\n"); }
  328.  
  329. main(int argc, char **argv)
  330. {
  331.   image_init();
  332.   jrand_init();
  333.   FILE *fp=fopen("art/mrphmask.spe","rb"); 
  334.   spec_directory sd(fp);
  335.   image *h1=new image(sd.find("20 h"),fp),
  336.         *h2=new image(sd.find("1h"),fp),
  337.         *i1=new image(sd.find("20"),fp),
  338.         *i2=new image(sd.find("1"),fp);
  339.   palette *pal=new palette(sd.find(SPEC_PALETTE),fp);
  340.   color_filter *fil=new color_filter(sd.find(SPEC_COLOR_TABLE),fp);  
  341.  
  342.   int steps=atoi(argv[1]);
  343.   if (steps<2) steps=50;
  344.   trans_image *hh1=new trans_image(h1,"hint1"),*hh2=new trans_image(h2,"hint2");
  345.  
  346.   time_marker time1;
  347.   super_morph sm(hh1,hh2,steps); 
  348.   int frames=atoi(argv[2]);
  349.   if (frames<2) frames=16;
  350.   smorph_player sp(&sm,pal,i1,i2,frames,-1); 
  351.  
  352.   time_marker time2;
  353.   dprintf("time = %lf\n",time2.diff_time(&time1));
  354.  
  355.   set_mode(19,argc,argv);
  356.   pal->load();
  357.   i1->put_image(screen,30,30);
  358.   update_dirty(screen);
  359.   sleep(2);
  360.   while (sp.show(screen,30,30,fil,pal)) 
  361.   { update_dirty(screen);
  362.     screen->bar(30,30,30+sp.w,30+sp.h,0);
  363.   }
  364.   sleep(2);
  365.   close_graphics();
  366. }*/
  367.  
  368.  
  369.